<html>
<head>
  <title>Data transfer to/from files and applications</title>
</head>
<body bgcolor="white" text="black">
<h1 align="center">Data transfer to/from files and applications</h1>

<p>The purpose of this library is to provide functions that allows data to be read/written without knowlegde of the origin/destination of the data (file or application). Note that RAMtransfer limits us to sequential data access.</p>

<h2 align="left">Data reading</h2>

<p>The main goal was to use a mechanism that would allow to use a single routine to read data from files (directly, because of a <code>EMsg_DataLoad</code> message or because of a <code>EMsg_DataSave</code> message leading to a scrap file) as well as direct RAMtransfer (<code>EMsg_DataSave</code>). Basically the routine would be a typical file reading routines from which we strip file opening/closing operations and replace the usual fread and similar calls by their stream independant equivalents so that it can be called in every circumstances. As a result loading routines takes the form of a <code>XFer_ReceiveProc</code> type function with as parameters:<p>

<pre><code>
void* handle      a pointer to the document which will contain the data
XFER  xfer        generic equivalent of a FILE*
file_type type    format of the data to read
ScreenPos* pPos   position on screen where the file was dropped as reported
                  by a Message_DataSave message (consecutive to a Drag &amp; Drop
                  or a clipboard paste) or NULL if consecutive to a
                  Message_DataLoad message or a direct file loading.
</code></pre>

<p>The function should use <code>XFer_ReceiveRead</code> calls to read data chunks (sorry no <code>XFer_ReceiveScanf</code> yet) and <code>XFer_GetErrorStatus</code> to check if an error occured or if the end of data is reached.</p>

<p>When you receive a <code>EMsg_DataLoad</code> or <code>EMsg_DataSave</code> message, call <code>XFer_Receive</code> passing as parameters the message, the callback and the pointer to the document. This will either initiate RAM transfer, call you routine and terminate RAM transfer or it will simply call <code>XFer_ReceiveFromFile</code> if RAM transfer is not possible.</p>

<p>When a file is to be read, call <code>XFer_ReceiveFromFile</code> passing as parameters the name of the file, the routine, the pointer to the document, and if relevant a position on screen. It will open the file, define the XFER stream, call your routine and close the file.</p>

<h2 align="left">Data saving</h2>

<p>I was not able to propose use a routine which write all the data sequentially as for a file because it would use a <code>Task_PostAndWaitForReply</code> mechanism for RAMtransfer as it does for data reading which would cause problems while saving data to our own task (a Wimp_Poll loop trying to exchange messages with another Wimp_Poll loop lower in the context stack). So instead I came up with a saving mechanism in which a <code>XFer_SendProc</code> type callback is repeatedly called by the transfer function until it return false. The parameters of the routine are:</p>

<pre><code>
void* handle        a pointer to the document containing the data to save
file_type type      format in which to save the data
sXFer_Chunk* pchunk a structure that contains on input:
                    ref   : reference of the data chunk to transfer,
                            always set to 0 on the first call
                    you are required to update is with:
                    pdata : pointer to the data chunk to transfer
                    size  : size of data chunk to transfer (all chunks doesn't
                            need to be of the same size)
                    ref   : ref of the next data chunk (index, pointer, ...)
</code></pre>

<p>However, there are a several points other than the data transfer itself to take into account when saving data:</p>

<ul>
  <li>The document should be marked as safe after the last chunk was transfered unless the transfer occured to an unsafe destination such as another application. So an <code>XFer_OnSafeProc</code> callback should be called if the data transfer was safe.</li>
  <li>The Drag &amp; Drop protocol (Acorn application note 241) allows for deletion of the source data after completion of the transfer in which case an <code>XFer_RemoveProc</code> callback should be called.</li>
  <li>The data may actually have been dragged to a printer in which case an <code>XFer_PrintProc</code> callback should be called instead of the <code>XFer_SendProc</code> one to print the data to a file which will be spooled to the printer (the protocol required for this is however not implemented yet).</li>
</li>
</ul>

<p>The transfer function that use such callbacks are:</p>

<ul>
  <li><code>DragDrop_Send</code>: used to transfer data on exit from a drag &amp; drop.</li>
  <li><code>XFer_Send</code>: used by <code>DragDrop_Send</code> and by the framework when another task request the contents of the Clipboard.</li>
  <li><code>XFer_SendToFile</code>: used to save a document when pressing ok on a save box or for a quick save (shift+F3).</li>
</ul>

<p>The parameters of these functions are described in the headers &quot;h.DragSend&quot; and &quot;h.XFer&quot;.

</body>
</html>